package com.example.function.integration.config.datasource;

import com.zaxxer.hikari.HikariDataSource;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

import static com.example.function.integration.constant.CommonConstant.MAPPER_SCAN_PATHS;

/**
 * @Description：定义一个数据源配置类，用于配置多个数据源
 * @Author：fengcheng
 * @Date：2024/11/8 10:12
 */
@Configuration
@MapperScan(basePackages = {MAPPER_SCAN_PATHS}, sqlSessionFactoryRef = "sqlSessionFactoryBean")
@Slf4j
public class DataSourceConfig {

    /**
     * spring.datasource.url=jdbc:mysql://localhost:3306/
     * spring.datasource.username=root
     * spring.datasource.password=secret
     *
     * @return
     */
     // 表示这个数据源是默认数据源, 如果有多个数据源，需要指定一个为主数据源
    @Primary
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource dataSource() {
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }

    /**
     * spring.datasource.a.url=jdbc:mysql://localhost:3306/
     * spring.datasource.a.username=root
     * spring.datasource.a.password=secret
     *
     * @return
     */
    @Bean(name = "aDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.a")
    public DataSource aDataSource() {
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }

    /**
     * spring.datasource.b.url=jdbc:mysql://localhost:3306/
     * spring.datasource.b.username=root
     * spring.datasource.b.password=secret
     *
     * @return
     */
    @Bean(name = "bDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.b")
    public DataSource bDataSource() {
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }

    /**
     * spring.datasource.c.url=jdbc:mysql://localhost:3306/
     * spring.datasource.c.username=root
     * spring.datasource.c.password=secret
     *
     * @return
     */
    @Bean(name = "cDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.c")
    public DataSource cDataSource() {
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }

    @Bean("dynamicDataSource")
    public DataSource dynamicDataSource() {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        Map<Object, Object> dataSourceMap = new HashMap<>(2);
        dataSourceMap.put("dataSource", dataSource());
        dataSourceMap.put("aDataSource", aDataSource());
        dataSourceMap.put("bDataSource", bDataSource());
        dataSourceMap.put("cDataSource", cDataSource());
        // 将 dataSource 数据源作为默认指定的数据源
        dynamicDataSource.setDefaultTargetDataSource(dataSource());
        // 将 dataSourceMap 数据源作为指定的数据源
        dynamicDataSource.setTargetDataSources(dataSourceMap);
        return dynamicDataSource;
    }

    /**
     * @Description：构建一个 SqlSessionFactoryBean 对象，用于创建 MyBatis 的 SqlSessionFactory 实例。
     * @Author：fengcheng
     * @Date：2024/11/8 09:58
     * @ParamsType：[]
     * @Return：org.mybatis.spring.SqlSessionFactoryBean
     */
    @Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean() throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        // 配置数据源，此处配置为关键配置，如果没有将 dynamicDataSource 作为数据源则不能实现切换
        sessionFactory.setDataSource(dynamicDataSource());
        sessionFactory.setTypeAliasesPackage(MAPPER_SCAN_PATHS);
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        sessionFactory.setMapperLocations(resolver.getResources("classpath*:mapper/**/*.xml"));    // 扫描映射文件
        // 切换数据源之后驼峰失效
        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
        configuration.setMapUnderscoreToCamelCase(true);
        sessionFactory.setConfiguration(configuration);
        return sessionFactory;
    }

    @Bean
    public PlatformTransactionManager transactionManager() {
        // 配置事务管理, 使用事务时在方法头部添加@Transactional注解即可
        return new DataSourceTransactionManager(dynamicDataSource());
    }

}
